/**
 * Title :	jFamilyTree generator
 * Description: jFamilyTree generator
 * Version:	provider
 * Copyright (c) 2001-2008
 * Terms of use:see license agreement at http://treebolic.sourceforge.net/en/license.htm
 * Author: Bernard Bou
 * Company: bsys
 */
package jFamilyTree.generator.domtree.treebolic;

import java.awt.Color;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;

import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;

import org.w3c.dom.Element;
import org.w3c.dom.Node;

import jFamilyTree.generator.domtree.DefaultDecorator;

/**
 * jFamilyTree-specific renderer
 * 
 * @author Bernard Bou
 */
public class Renderer extends jFamilyTree.generator.domtree.Renderer
{
	private static final long serialVersionUID = 1L;

	// icons

	/**
	 * Node icon
	 */
	static protected ImageIcon theNodeIcon;

	/**
	 * Edge icon
	 */
	static protected ImageIcon theEdgeIcon;

	/**
	 * Link icon
	 */
	static protected ImageIcon theLinkIcon;

	// styles

	/**
	 * Style for node name
	 */
	static private SimpleAttributeSet theNodeNameStyle = new SimpleAttributeSet();

	/**
	 * Style for node data
	 */
	static private SimpleAttributeSet theNodeValueStyle = new SimpleAttributeSet();

	/**
	 * Style for edge name
	 */
	static private SimpleAttributeSet theEdgeNameStyle = new SimpleAttributeSet();

	/**
	 * Style for link name
	 */
	static private SimpleAttributeSet theLinkNameStyle = new SimpleAttributeSet();

	/**
	 * Style for edge data
	 */
	static private SimpleAttributeSet theEdgeValueStyle = new SimpleAttributeSet();

	/**
	 * Style for link data
	 */
	static private SimpleAttributeSet theLinkValueStyle = new SimpleAttributeSet();

	/**
	 * Style for src data
	 */
	static private SimpleAttributeSet theSrcStyle = new SimpleAttributeSet();

	/**
	 * Edge ends style
	 */
	static private SimpleAttributeSet theEdgeEndsStyle = new SimpleAttributeSet();

	// patterns
	
	/**
	 * Src pattern
	 */
	private Pattern theSrcPattern = Pattern.compile("src=\"(([^\"]*))\""); //$NON-NLS-1$

	/**
	 * From pattern
	 */
	private Pattern theFromPattern = Pattern.compile("from=\"(([^\"]*))\""); //$NON-NLS-1$

	/**
	 * To pattern
	 */
	private Pattern theToPattern = Pattern.compile("to=\"(([^\"]*))\""); //$NON-NLS-1$

	// maps
	
	/**
	 * Name styles for classes
	 */
	private Map<String, SimpleAttributeSet> theTypeToNameStyleMap;

	/**
	 * Value styles for classes
	 */
	private Map<String, SimpleAttributeSet> theTypeToValueStyleMap;

	/**
	 * Icons for classes
	 */
	private Map<String, Icon> theTypeToIconMap;

	static
	{
		// name styles
		StyleConstants.setFontFamily(theNodeNameStyle, "Dialog"); //$NON-NLS-1$
		StyleConstants.setFontSize(theNodeNameStyle, 11);
		StyleConstants.setBold(theNodeNameStyle, true);
		StyleConstants.setForeground(theNodeNameStyle, Color.BLACK);
		StyleConstants.setBackground(theNodeNameStyle, Color.ORANGE);

		StyleConstants.setFontFamily(theEdgeNameStyle, "Dialog"); //$NON-NLS-1$
		StyleConstants.setFontSize(theEdgeNameStyle, 11);
		StyleConstants.setBold(theEdgeNameStyle, true);
		StyleConstants.setForeground(theEdgeNameStyle, Color.BLACK);
		StyleConstants.setBackground(theEdgeNameStyle, Color.ORANGE);

		StyleConstants.setFontFamily(theLinkNameStyle, "Dialog"); //$NON-NLS-1$
		StyleConstants.setFontSize(theLinkNameStyle, 11);
		StyleConstants.setBold(theLinkNameStyle, true);
		StyleConstants.setForeground(theLinkNameStyle, Color.WHITE);
		StyleConstants.setBackground(theLinkNameStyle, Color.BLUE);

		// value styles
		StyleConstants.setFontFamily(theNodeValueStyle, "Dialog"); //$NON-NLS-1$
		StyleConstants.setFontSize(theNodeValueStyle, 10);
		StyleConstants.setForeground(theNodeValueStyle, Color.BLACK);

		StyleConstants.setFontFamily(theEdgeValueStyle, "Dialog"); //$NON-NLS-1$
		StyleConstants.setFontSize(theEdgeValueStyle, 10);
		StyleConstants.setForeground(theEdgeValueStyle, Color.BLACK);

		StyleConstants.setFontFamily(theLinkValueStyle, "Dialog"); //$NON-NLS-1$
		StyleConstants.setFontSize(theLinkValueStyle, 10);
		StyleConstants.setForeground(theLinkValueStyle, Color.BLACK);

		// pattern styles
		StyleConstants.setForeground(theSrcStyle, Color.MAGENTA);

		// images
		theNodeIcon = new ImageIcon(Renderer.class.getResource("images/treenode.gif")); //$NON-NLS-1$
		theEdgeIcon = new ImageIcon(Renderer.class.getResource("images/treeedge.gif")); //$NON-NLS-1$
		theLinkIcon = new ImageIcon(Renderer.class.getResource("images/treelink.gif")); //$NON-NLS-1$
	}

	/**
	 * Constructor
	 */
	public Renderer()
	{
		// styles for class
		theTypeToNameStyleMap = new HashMap<String, SimpleAttributeSet>();
		theTypeToNameStyleMap.put("node", theNodeNameStyle); //$NON-NLS-1$
		theTypeToNameStyleMap.put("edge", theNodeNameStyle); //$NON-NLS-1$
		theTypeToNameStyleMap.put("a", theLinkNameStyle); //$NON-NLS-1$
		theTypeToValueStyleMap = new HashMap<String, SimpleAttributeSet>();
		theTypeToValueStyleMap.put("node", theEdgeValueStyle); //$NON-NLS-1$
		theTypeToValueStyleMap.put("edge", theEdgeValueStyle); //$NON-NLS-1$
		theTypeToValueStyleMap.put("a", theLinkValueStyle); //$NON-NLS-1$

		// styles for patterns
		thePatterns.add(theSrcPattern);
		thePatterns.add(theFromPattern);
		thePatterns.add(theToPattern);
		thePatternToStyleMap.put(theSrcPattern, theSrcStyle);
		thePatternToStyleMap.put(theFromPattern, theEdgeEndsStyle);
		thePatternToStyleMap.put(theToPattern, theEdgeEndsStyle);

		// icons for class
		theTypeToIconMap = new HashMap<String, Icon>();
		theTypeToIconMap.put("node", theNodeIcon); //$NON-NLS-1$
		theTypeToIconMap.put("edge", theEdgeIcon); //$NON-NLS-1$
		theTypeToIconMap.put("a", theLinkIcon); //$NON-NLS-1$
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see jFamilyTree.generator.domtree.Renderer#getIconStyle(org.w3c.dom.Node)
	 */
	@Override
	protected Icon getIconStyle(Node thisNode)
	{
		if (thisNode instanceof Element)
		{
			Element thisElement = (Element) thisNode;
			Icon thisIcon = theTypeToIconMap.get(thisElement.getNodeName());
			if (thisIcon != null)
				return thisIcon;
		}
		return super.getIconStyle(thisNode);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see jFamilyTree.generator.domtree.Renderer#getNameStyle(org.w3c.dom.Node)
	 */
	@Override
	protected SimpleAttributeSet getNameStyle(Node thisNode)
	{
		if (thisNode instanceof Element)
		{
			Element thisElement = (Element) thisNode;
			SimpleAttributeSet thisStyle = theTypeToNameStyleMap.get(thisElement.getNodeName());
			if (thisStyle != null)
				return thisStyle;
		}
		return super.getNameStyle(thisNode);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see jFamilyTree.generator.domtree.Renderer#getValueStyle(org.w3c.dom.Node)
	 */
	@Override
	protected SimpleAttributeSet getValueStyle(Node thisNode)
	{
		if (thisNode instanceof Element)
		{
			Element thisElement = (Element) thisNode;
			SimpleAttributeSet thisStyle = theTypeToValueStyleMap.get(thisElement.getNodeName());
			if (thisStyle != null)
				return thisStyle;
		}
		return super.getValueStyle(thisNode);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see jFamilyTree.generator.domtree.Renderer#makeDecorator(org.w3c.dom.Node)
	 */
	@Override
	protected DefaultDecorator makeDecorator(Node thisNode)
	{
		if (thisNode.getNodeType() != Node.ELEMENT_NODE)
			return super.makeDecorator(thisNode);

		Element thisElement = (Element) thisNode;
		String thisTag = thisElement.getTagName();
		if (thisTag.equals("node")) //$NON-NLS-1$
			return new NodeDecorator(thisElement);
		else if (thisTag.equals("edge")) //$NON-NLS-1$
			return new EdgeDecorator(thisElement);
		else if (thisTag.equals("a")) //$NON-NLS-1$
			return new LinkDecorator(thisElement);
		return super.makeDecorator(thisNode);
	}
}